package kayao.server.threads;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Vector;

import kayao.common.Client;
import kayao.common.KayaoValues;
import kayao.common.NetworkUtils;
import kayao.server.AreaManager;
import kayao.server.DesktopServer;


public class KingsRequestThread extends Thread {

	protected String address=null;
	protected int port;
	protected DatagramSocket socket=null;
	protected byte []dataReceived=null;
	
	public KingsRequestThread(String a, int p, byte [] d, DatagramSocket s) {
		address = a;
		port = p;
		dataReceived=d;
		socket=s;
	}

	public void run()
	{
		try
		{
			byte []value=new byte[4];
			//get the counter
			System.arraycopy(dataReceived, 5, value, 0, 4);
			int counter = NetworkUtils.insertByteArrayToInt(dataReceived, 5);

			//get the id (int32)
			System.arraycopy(dataReceived, 9, value, 0, 4);
			int id = NetworkUtils.insertByteArrayToInt(dataReceived, 9);

			//get the number of requests (one byte)
			System.arraycopy(dataReceived, 13, value, 0, 1);
			int number = NetworkUtils.unsignedByteToInt(value[0]);
			
			// Create the array with data to send
			//The method calculate size DOES the update of the kings
			//It's needed to be done before create the answer because of its size
			byte[] data = new byte[calculateSize(id,number)];//10 + (10+length) * number

			int index=0;
			//coping the magic number (already checked)
			System.arraycopy(dataReceived, 0, data, index, 4);
			index+=4;
			//id message
			data[index] = KayaoValues.KING_REQUEST_REPLY_MESSAGE;
			index++;
			//counter
			NetworkUtils.insertIntToByteArray(data, index, counter);
			index+=4;
			
			//copying the number of requests to send too
			data[index]=(byte)number;
			index++;

			//get the requests
			int kingid,kingdom;
			int index2=14;
			
			for(int i=0;i<number;i++)
			{
				//get the kingdom in value
				System.arraycopy(dataReceived, index2, value, 0, 1);
				//increase the reading index
				index2++; 
				//transform it to an integer
				kingdom=NetworkUtils.unsignedByteToInt(value[0]);
				//get the king WITHOUT MODIFY IT
				kingid=AreaManager.getKingByRegion(kingdom);
				System.out.println("[KingRequestThread] - Applicant ID:"+ id + ", Kingdom: " + kingdom+", KingID: "+ kingid);
				//write its data
				if(kingid==0 )
				{
					NetworkUtils.insertIntToByteArray(data,index,0);
					index+=4;
				} 
				else 
				{
					//id+teamid+length+name+ip
					Client c=DesktopServer.getClient(kingid);
					NetworkUtils.insertIntToByteArray(data, index, c.getId());
					index+=4;
					data[index]=(byte)c.getTeam();
					index++;
					//length
					data[index]=(byte)c.getName().length();
					index++;
					//name
					for(int j=0; j<c.getName().length();j++)
					{
						data[index]=(byte) c.getName().charAt(j);
						index++;
					}
					//ip
					//System.out.println("KingsRequestThread (ip) \t index: "+index+" data.length: "+data.length);
					System.arraycopy(InetAddress.getByName(c.getIP()).getAddress(), 0, data, index, 4);
					index+=4;
				}
			}
			
			//Send the answer packet
			InetAddress add=InetAddress.getByName(address);
			socket.send(new DatagramPacket(data,data.length, add, port));
			System.out.println("King request answered with " + data.length +" bytes.\n");
		}
		catch(Exception e)
		{
			//Basic treatment at the moment... show message and restart the reading
			e.printStackTrace();
			System.out.println("KingsRequestThread Error: "+ e.getMessage());
			//Some exceptions...
		}
	}

	private int calculateSize(int id, int number) {
		byte value[]=new byte[4];
		int size=10;
		int region=0;
		AreaManager.deleteKingById(id);
		//10 + (10+length) * number
		int index=14;
		Vector<Integer> regions=new Vector<Integer>();
		for(int i=0;i<number;i++)
		{
			//get kingdom in value
			System.arraycopy(dataReceived, index, value, 0, 1);
			index++;
			//the first kingdom will be its region
			if(i==0)region=NetworkUtils.unsignedByteToInt(value[0]);
			//convert the kingdom
			int kingdom=NetworkUtils.unsignedByteToInt(value[0]);
			regions.add(kingdom);
			//Check out the king. Change if it's needed
			int kingid=AreaManager.checkKing(id, region, kingdom);
			//Increase the size depending of the result of the checkKing
			if(kingid==0)size+=4;
			else//id+teamid+length+name+ip
				size+=(4+1+1+4+DesktopServer.getClient(kingid).getName().length());
		}
		//System.out.println("[KingRequest] - Size: " + size);
		AreaManager.removeInterestInRegions(id,regions);
		return size;
	}	
}
